package com.rags.chess.game;

import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.rags.chess.base.Color;
import com.rags.chess.base.Coordinate;
import com.rags.chess.base.Piece;
import com.rags.chess.move.BasicMove;
import com.rags.chess.move.EnPassant;
import com.rags.chess.move.IllegalMoveException;
import com.rags.chess.move.Move;
import com.rags.chess.pieces.King;

public class GameHelper {
	private static Log log = LogFactory.getLog(GameHelper.class);
	
	public static boolean isInCheck(Game game, Color color) {
		Collection<Piece> pieces = game.getPieces(color);
		King king = null;
		for (Piece p : pieces)
			if (p instanceof King) {
				king = (King)p;
				break;
			}
		Collection<Piece> oppositionPieces = game.getPieces(color == Color.WHITE? Color.BLACK : Color.WHITE);
		for (Piece oppositionPiece : oppositionPieces) {
			if (oppositionPiece.isValidMove(game, king.getPosition()))
				return true;
		}
		return false;
	}
	
	public static boolean isInCheckmate(Game game, Color color) {
		if (!isInCheck(game, color))
			return false;
		return isCheckmateOrStalemate(game, color);
	}
	
	public static boolean isInStalemate(Game game, Color color) {
		if (isInCheck(game, color))
			return false;
		return isCheckmateOrStalemate(game, color);
	}
	
	private static boolean isCheckmateOrStalemate(Game game, Color color) {
		log.debug(String.format("Checking if %s is in checkmate or stalemate", color));
		Collection<Piece> pieces = game.getPieces(color);
		log.debug(String.format("%s pieces are %s", color, pieces));
		for (Piece p : pieces)
			for (int i=0; i<8; i++)
				for (int j=0; j<8; j++) {
					Coordinate destination = new Coordinate(i, j);
					Move move = null;
					try {
						move = new EnPassant(game, p.getPosition(), destination);
					} catch(IllegalArgumentException e) {
						move = null;
					} catch(IllegalMoveException e) {
						move = null;
					}
					if (p.isValidMove(game, destination) || move != null) {
						if (move == null) 
							log.debug(String.format("%s %s, moving from %s to %s", p.getColor(), p.getClass().getSimpleName(), p.getPosition(), destination));
						else
							log.debug(String.format("En passant, %s pawn from %s to %s", p.getColor(), p.getPosition(), destination));
						
						Game newGame = new Game(game);
							if (move != null)
								move = new UncheckedEnPassant(newGame, p.getPosition(), destination);
							else
								move = new UncheckedBasicMove(newGame, p.getPosition(), destination);
							move.makeMove();
							if (!GameHelper.isInCheck(newGame, p.getColor()))
								return false;
							continue;
					}
				}
		return true;
	}
	
	private static class UncheckedBasicMove extends BasicMove {
		public UncheckedBasicMove(Game game, Coordinate start, Coordinate anEnd) {
			super(game, start, anEnd);
		}
		
		@Override
		protected String deriveNotation(Game game, Coordinate start, Coordinate end) {
			return "";
		}
		
		@Override
		protected String checkNotation() {
			return "";
		}
		
		@Override
		protected boolean isInCheck(Game g, Coordinate begin, Coordinate finish) {
			return false;
		}
	}
	
	private static class UncheckedEnPassant extends EnPassant {
		public UncheckedEnPassant(Game game, Coordinate start, Coordinate anEnd) {
			super(game, start, anEnd);
		}
		
		@Override
		protected String deriveNotation(Game game, Coordinate start, Coordinate end) {
			return "";
		}
		
		@Override
		protected String checkNotation() {
			return "";
		}
		
		@Override
		protected boolean isInCheck(Game g, Coordinate begin, Coordinate finish) {
			return false;
		}
	}
}
